package com.sherlockHolmes.init.base.utils;

import com.fasterxml.jackson.databind.JsonNode;
import com.maxmind.db.Reader;
import com.maxmind.db.Record;
import com.maxmind.geoip2.DatabaseReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 *
 * @description: 获取客户端IP地址/根据IP地址获取所在区域及经纬度
 * @author: lcx
 * @since: 2020年07月02日 上午11:25:51
 */
public class IPUtils {
    private static Logger logger = LoggerFactory.getLogger(IPUtils.class);
    private final static String INTRANET_LOCAL_IP = "127.0.0.1";
    /**
     * 获取客户端真实IP
     * 使用Nginx等反向代理软件， 则不能通过request.getRemoteAddr()获取IP地址
     * 如果使用了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP地址，
     * X-Forwarded-For中第一个非unknown的有效IP字符串，则为真实IP地址
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if (ip.equals(INTRANET_LOCAL_IP)) {
                // 根据网卡取本机配置的IP
                InetAddress inet;
                try {
                    inet = InetAddress.getLocalHost();
                    if (null != inet) {
                        ip = inet.getHostAddress();
                    }
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
            }
        }

        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ip != null && ip.length() > 15) {
            if (ip.indexOf(",") > 0) {
                ip = ip.substring(0, ip.indexOf(","));
            }
        }
        return ip;
    }
    /**
     *
     * @description: 获得国家
     * @param reader
     * @param ip
     * @return
     * @throws Exception
     */
    public static String getCountry(DatabaseReader reader, String ip) throws Exception {
        return reader.city(InetAddress.getByName(ip)).getCountry().getNames().get("zh-CN");
    }

    /**
     *
     * @description: 获得省份
     * @param reader
     * @param ip
     * @return
     * @throws Exception
     */
    public static String getProvince(DatabaseReader reader, String ip) throws Exception {
        return reader.city(InetAddress.getByName(ip)).getMostSpecificSubdivision().getNames().get("zh-CN");
    }

    /**
     *
     * @description: 获得城市
     * @param reader
     * @param ip
     * @return
     * @throws Exception
     */
    public static String getCity(DatabaseReader reader, String ip) throws Exception {
        return reader.city(InetAddress.getByName(ip)).getCity().getNames().get("zh-CN");
    }

    /**
     *
     * @description: 获得经度
     * @param ip
     * @return
     * @throws Exception
     */
    public static Double getLongitude(String ip) throws Exception {
        String path = "F:/gitee/project-template/src/main/resources/db/GeoLite2-City.mmdb";
        File database = new File(path);
        // 读取数据库内容
        DatabaseReader reader = new DatabaseReader.Builder(database).build();
        return reader.city(InetAddress.getByName(ip)).getLocation().getLongitude();
    }

    /**
     *
     * @description: 获得纬度
     * @param ip
     * @return
     * @throws Exception
     */
    public static Double getLatitude(String ip) throws Exception {
        String path = "F:/gitee/project-template/src/main/resources/db/GeoLite2-City.mmdb";
        File database = new File(path);
        // 读取数据库内容
        DatabaseReader reader = new DatabaseReader.Builder(database).build();
        return reader.city(InetAddress.getByName(ip)).getLocation().getLatitude();
    }
//    public static void main(String[] args) throws Exception {
//        String ip = "115.236.64.138"; // 访问IP
//        // 实际项目中可存放在resources下通过注解加载或配置pom.xml文件启动项目时加载扫描均可,若有更简便方式更好
//        String path = "F:/gitee/project-template/src/main/resources/db/GeoLite2-City.mmdb";
//        //String path ="F:/gitee/project-template/src/main/resources/db/Country.mmdb";
//        // 创建 GeoLite2 数据库
//        File database = new File(path);
//        test1(ip, database);
//        System.out.println("..............................................................");
//        test2(ip, database);
//    }

//    private static void test1(String ip, File database)throws Exception{
//        // 读取数据库内容
//        DatabaseReader reader = new DatabaseReader.Builder(database).build();
//        String address1 = IPUtils.getCountry(reader, ip) + "-" + IPUtils.getProvince(reader, ip) + "-" + IPUtils.getCity(reader, ip)
//                + "-经度" + IPUtils.getLongitude(reader, ip)+ "-纬度" + IPUtils.getLatitude(reader, ip);
//        System.out.println(address1);
//    }
//
//    private static void test2(String ip, File database)throws Exception{
//        try (Reader reader = new Reader(database)) {
//            InetAddress address = InetAddress.getByName(ip);
//            // get() returns just the data for the associated record
//            JsonNode recordData = reader.get(address);
//            System.out.println(recordData);
//            // getRecord() returns a Record class that contains both
//            // the data for the record and associated metadata.
////            Record record = reader.getRecord(address);
////            System.out.println(record.getData());
////            System.out.println(record.getNetwork());
//        }
//    }
}
